package com.fwmagic.rpc.handler;

import com.fwmagic.rpc.service.pojo.RpcRequest;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Method;
import java.net.Socket;

/**
 * 接受客户端请求，调用服务方法，返回结果值
 */
public class ProcessHandler implements Runnable {

    private Socket socket;

    private Object service;

    public ProcessHandler() {
    }

    public ProcessHandler(Socket socket, Object service) {
        this.socket = socket;
        this.service = service;
    }

    public void run() {
        ObjectInputStream in = null;
        ObjectOutputStream out = null;
        try {
            in = new ObjectInputStream(socket.getInputStream());

            //从socket输入流中获取RpcRequest:请求方法，请求参数，请求参数类型
            RpcRequest rpcRequest = (RpcRequest) in.readObject();

            //反射调用方法获取结果
            Object invoke = invoke(rpcRequest);

            //返回结果给客户端
            out = new ObjectOutputStream(socket.getOutputStream());
            out.writeObject(invoke);
            out.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
        }
    }

    /**
     * 反射调用目标方法
     * @param rpcRequest
     * @return
     */
    private Object invoke(RpcRequest rpcRequest) {
        String methodName = rpcRequest.getMethodName();
        Object[] args4Method = rpcRequest.getArgs4Method();
        Class[] paramTypes = rpcRequest.getParamTypes();
        try {
            Method method = service.getClass().getMethod(methodName, paramTypes);
            Object invoke = method.invoke(service, args4Method);
            return invoke;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
